/*
 * ProtoA.c
 *
 */ 

#include <avr/io.h>

#include <avr/eeprom.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <avr/interrupt.h>

// Only because I don't have enough cables
#define DEV_TEMPERATURE 1
#define DEV_WIND_VANE 1
#define DEV_ANEMOMETER 1
#define DEV_CLOCK 1
#define DEV_LCD 1




#include "SPI.h"
#include "UART.h"
#include "Clock.h"
#include "I2C.h"


#if DEV_TEMPERATURE
	#include "Termometer.h"
#endif

#if DEV_WIND_VANE 
	#include "WindVane.h"
#endif

#include "Anemometer.h"

#if DEV_LCD
	#include "LCD.h"
	uint8_t lcd_refresh_time=1;
	int32_t lcd_last=-4;
	uint8_t lcd_index=0;
#endif

uint16_t temperature;
uint8_t windSpeed;
uint16_t windDirection;

// Functions declarations
void print();
void take_samples();
void send_data();
void init_drivers();


typedef  uint32_t mem_block_t;

//////////////////////////////////////////////////////////////////////////
//																		//
//								Main									//
//																		//
//////////////////////////////////////////////////////////////////////////
int main(void)
{
	// Sample timing
	uint8_t sample_time=1;
	int32_t last_sample=-sample_time;
	
	// Memory
	mem_block_t *mem_next=0;
	mem_block_t block;
	


	init_drivers();
	LCD_Clear();
	LCD_WriteString("initial");


	//
	//	Main Loop
	//
	while(1)
	{
		//
		//	Take samples 
		//
		if(seconds - last_sample >= sample_time)
		{
			last_sample=seconds;
			take_samples();
			//
			// Write into memory
			block=0;
			block+= (uint32_t)(temperature) << 16;
			block+=(uint32_t)(windDirection) << 7;
			block+=windSpeed;
			
			eeprom_busy_wait();
			eeprom_write_block(&block,mem_next,sizeof(block));

			mem_next++;
		}
		
		//			
		// Show Results
		//
		print();
		
		//
		// UART
		//
		if(UART_ReadyRead())
		{
			char byte=UART_ReadByte();
			//
			//	Send Data
			//
			if(byte==20)
			{
				mem_block_t *pBlock=0;
				while(pBlock!=mem_next)
				{
					eeprom_busy_wait();
					eeprom_read_block(&block,pBlock,sizeof(block));
					UART_WriteBlock(&block,sizeof(block));
					
					pBlock++;
				}
				
				// End of transmission
				block=0x70000000;
				UART_WriteBlock(&block,sizeof(block));	
				mem_next=0;				
			}
			//
			//	Config
			//
			else if(byte==40)
			{
				
				date_t date;
				
				date.year=UART_ReadByte();
				date.month=UART_ReadByte();
				date.day=UART_ReadByte();
				date.hour=UART_ReadByte();
				date.minutes=UART_ReadByte();
				date.seconds=UART_ReadByte();
				
				sample_time=UART_ReadByte();
				
				// Clear memory
				mem_next=0;
				
				Clock_SetDate(date);
				
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
//																		//
//							Init Drivers								//
//																		//
//////////////////////////////////////////////////////////////////////////
void init_drivers()
{
		//
	// Init drivers
	//
	cli();
	
	UART_Init(9600,8);
	SPI_Init();
	
	#if DEV_CLOCK
		Clock_Init();
		Clock_SetDate(Clock_CreateDate(12,1,1,0,0,0));
	#endif
	
	#if DEV_TEMPERATURE
		I2C_init();
	#endif
	
	Vane_Init();
	ANEMO_Init();
	
	
	#if DEV_LCD
		uint8_t lcd_refresh_time=4;
		uint32_t lcd_last=-lcd_refresh_time;
		uint8_t lcd_index = 0;
		
		LCD_Init();
	#endif
	


	sei();
}

//////////////////////////////////////////////////////////////////////////
//																		//
//								Print									//
//																		//
//////////////////////////////////////////////////////////////////////////

void print()
{
	#if DEV_LCD
		if( seconds - lcd_last >= lcd_refresh_time)
		{
			lcd_last=seconds;
				
			switch(lcd_index)	
			{
				// Temperature	
				case 0:
				{
					// Integer part
					int8_t intpart=(int8_t)(temperature >> 1);
					
					char aux[30];
					// .5 ??
					if( (temperature & 0x01) )
						sprintf(aux,"Temp: % 2d.%1d",intpart,5);
					else
						sprintf(aux,"Temp: % 2d",intpart);
					
					LCD_Clear();
					LCD_WriteString(aux);
				}
				break;
					
				// Direction
				case 1:
				{
					char aux[30];
					sprintf(aux,"Wind Dir: %3d",windDirection);
					LCD_Clear();
					LCD_WriteString(aux);
				}			
				break;
				// Wind Speed
				case 2:		
				{
					char aux[30];
					double inpart;
					float floatpart= modf(ANEMO_FreqToMS(windSpeed),&inpart)*100;
						
					LCD_Clear();
					LCD_WriteString("Wind Speed");
						
					LCD_GotoXY(0,1);
					if(floatpart)
						sprintf(aux,"%d.%d m/s",(int)inpart,(int)floatpart);
					else
						sprintf(aux,"%d m/s",(int)inpart);
					LCD_Clear();
					LCD_WriteString(aux);
						
				}
				break;		
				
				
				case 3:
					{
						date_t d=Clock_Date();
						char aux[30];
						sprintf(aux,"%2d/%02d/%02d",d.year,d.month,d.day);
						LCD_Clear();
						LCD_WriteString(aux);
						
						sprintf(aux,"% 2d:%02d:%02d",d.hour,d.minutes,d.seconds);
						LCD_GotoXY(0,1);
						LCD_WriteString(aux);
						
					}	
				break;						
			}	// Switch
				
				
			lcd_index++;
			lcd_index=lcd_index % 4;
		}
	#endif /* DEV_LCD */
}

//////////////////////////////////////////////////////////////////////////
//																		//
//								sample									//
//																		//
//////////////////////////////////////////////////////////////////////////

void take_samples()
{

		#if DEV_TEMPERATURE
			temperature=Temp_Read();
			
		#else
			// 20.5
			temperature= (20 << 1) + 1;
		#endif 
		
		#if DEV_WIND_VANE
			windDirection = Vane_Read();
			
		#else
			// NE
			windDirection  = 45 ;
		#endif
				
		#if DEV_ANEMOMETER
			windSpeed = ANEMO_Read();
		#else
			windSpeed = 40;
		#endif
}			
